#!/usr/bin/env bash
set -euox pipefail

ARCHITECTURES=(
    amd64
    arm
    arm64
    ppc64le
    s390x
    mips64le
)

# Prepare the system
REGISTRY=${REGISTRY:-gcr.io/k8s-staging-cri-tools}
QEMUVERSION=5.2.0-2

export DOCKER_CLI_EXPERIMENTAL=enabled
gcloud auth configure-docker
docker run --rm --privileged multiarch/qemu-user-static:$QEMUVERSION --reset -p yes >/dev/null
BUILDER=$(docker buildx create --use)

cleanup() {
    docker buildx rm "$BUILDER"
}

trap cleanup EXIT

build_image() {
    DIR=$1
    IMAGE=$2
    ARGS=("${@:3}")

    IMAGE_NAMES=()
    for ARCH in "${ARCHITECTURES[@]}"; do
        FULL_IMAGE_NAME="$REGISTRY/$IMAGE-$ARCH:latest"
        IMAGE_NAMES+=("$FULL_IMAGE_NAME")

        docker buildx build \
            --pull \
            --load \
            --platform "linux/$ARCH" \
            -t "$FULL_IMAGE_NAME" \
            "${ARGS[@]}" \
            "$DIR"
        docker push "$FULL_IMAGE_NAME"
    done

    MANIFEST="$REGISTRY/$IMAGE:latest"
    docker manifest create --amend "$MANIFEST" "${IMAGE_NAMES[@]}"
    for ARCH in "${ARCHITECTURES[@]}"; do
        FULL_IMAGE_NAME="$REGISTRY/$IMAGE-$ARCH:latest"
        docker manifest annotate --arch "$ARCH" "$MANIFEST" "$FULL_IMAGE_NAME"
    done
    docker manifest push "$MANIFEST"
}

# Build the user images
declare -A IMAGE_USERS
IMAGE_USERS=(
    ["test-image-user-uid"]="1002"
    ["test-image-user-username"]="www-data"
    ["test-image-user-uid-group"]="1003:1004"
    ["test-image-user-username-group"]="www-data:1004"
)

for IMAGE in "${!IMAGE_USERS[@]}"; do
    USER=${IMAGE_USERS[$IMAGE]}
    build_image ./image-user "$IMAGE" --build-arg "USER=$USER"
done

# Build the hostnet image
build_image ./hostnet-nginx hostnet-nginx

# Build the windows images
declare -A IMAGE_WINDOWS
IMAGE_WINDOWS=(
    ["win-test-image-1"]="latest"
    ["win-test-image-2"]="latest"
    ["win-test-image-3"]="latest"
    ["win-test-image-latest"]="latest"
    ["win-test-image-digest"]="latest"
)
WIN_DIR=image-test-win
for IMAGE in "${!IMAGE_WINDOWS[@]}"; do
    TAG=${IMAGE_WINDOWS[$IMAGE]}
    touch "$WIN_DIR/$IMAGE"
    docker buildx build \
        --pull --push \
        --platform "windows/amd64" \
        --build-arg "TEST=$IMAGE" \
        -t "$REGISTRY/$IMAGE:$TAG" \
        $WIN_DIR
    rm -f "$WIN_DIR/$IMAGE"
done

IMAGE=win-test-image-tags
touch "$WIN_DIR/$IMAGE"
docker buildx build \
    --pull --push \
    --platform "windows/amd64" \
    --build-arg "TEST=$IMAGE" \
    -t "$REGISTRY/$IMAGE:1" \
    -t "$REGISTRY/$IMAGE:2" \
    -t "$REGISTRY/$IMAGE:3" \
    $WIN_DIR
rm -f "$WIN_DIR/$IMAGE"

IMAGE=win-test-image-tag
touch "$WIN_DIR/$IMAGE"
docker buildx build \
    --pull --push \
    --platform "windows/amd64" \
    --build-arg "TEST=$IMAGE" \
    -t "$REGISTRY/$IMAGE:test" \
    -t "$REGISTRY/$IMAGE:all" \
    $WIN_DIR
rm -f "$WIN_DIR/$IMAGE"

# Build the other test images
IMAGE_TEST=(
    test-image-1
    test-image-2
    test-image-3
    test-image-latest
    test-image-digest
)
DIR=image-test
for IMAGE in "${IMAGE_TEST[@]}"; do
    touch "$DIR/$IMAGE"
    build_image "$DIR" "$IMAGE" --build-arg "TEST=$IMAGE"
    rm -f "$DIR/$IMAGE"
done

# Build test-image-tags
IMAGE_NAMES=()
IMAGE=test-image-tags
TAGS=(1 2 3)
touch $DIR/same-image
for ARCH in "${ARCHITECTURES[@]}"; do
    for TAG in "${TAGS[@]}"; do
        FULL_IMAGE_NAME="$REGISTRY/$IMAGE-$ARCH:$TAG"
        IMAGE_NAMES+=("$FULL_IMAGE_NAME")

        docker buildx build \
            --pull \
            --load \
            --platform "linux/$ARCH" \
            -t "$FULL_IMAGE_NAME" \
            --build-arg TEST=same-image \
            "$DIR"

        docker push "$FULL_IMAGE_NAME"
    done
done
rm -f $DIR/same-image

for TAG in "${TAGS[@]}"; do
    MANIFEST="$REGISTRY/$IMAGE:$TAG"
    docker manifest create --amend "$MANIFEST" "${IMAGE_NAMES[@]}"
    for ARCH in "${ARCHITECTURES[@]}"; do
        FULL_IMAGE_NAME="$REGISTRY/$IMAGE-$ARCH:$TAG"
        docker manifest annotate --arch "$ARCH" "$MANIFEST" "$FULL_IMAGE_NAME"
    done
    docker manifest push "$MANIFEST"
done

# Build test-image-tag
IMAGE_NAMES=()
IMAGE=test-image-tag
TAGS=(test all)
for TAG in "${TAGS[@]}"; do
    touch "$DIR/$TAG"
    for ARCH in "${ARCHITECTURES[@]}"; do
        FULL_IMAGE_NAME="$REGISTRY/$IMAGE-$ARCH:$TAG"
        IMAGE_NAMES+=("$FULL_IMAGE_NAME")

        docker buildx build \
            --pull \
            --load \
            --platform "linux/$ARCH" \
            -t "$FULL_IMAGE_NAME" \
            --build-arg "TEST=$TAG" \
            "$DIR"

        docker push "$FULL_IMAGE_NAME"
    done
    rm -f "$DIR/$TAG"

    MANIFEST="$REGISTRY/$IMAGE:$TAG"
    docker manifest create --amend "$MANIFEST" "${IMAGE_NAMES[@]}"
    for ARCH in "${ARCHITECTURES[@]}"; do
        FULL_IMAGE_NAME="$REGISTRY/$IMAGE-$ARCH:$TAG"
        docker manifest annotate --arch "$ARCH" "$MANIFEST" "$FULL_IMAGE_NAME"
    done
    docker manifest push "$MANIFEST"
done
